/**
 * Require: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
 * Usage:   <script src="https://epp-jslib.googlecode.com/hg-history/tip/src/epp-csv.js"></script>
 **/

function EppCsv() {}

/** 
 * Quebra em linhas e colunas. 
 * parse(texto[, separador])
 * separador: ',' se não informado
 */
EppCsv.parse = function (texto, separador) {
	separador = separador ? separador : ',';
	var csv = [];
	var lines = texto.split('\n');
   	for (var i = 0 ; i < lines.length; i++) {
   		var splitted = EppCsv._splitLine(lines[i], separador)
   		if(splitted) csv.push(splitted);
   	};
   	return csv;
}

/** 
 * Quebra em linhas e colunas criando um objeto para cada linha. As chaves do objeto são obtidas do
 * paramentro headers, qdo informado, ou da primeira linha.
 * parseObjects(texto[, separador[, headers]])
 * separador: ',' se não informado
 * headers: usa a primeira linha se não informado
 */
EppCsv.parseObjects = function (texto, separador, headers) {
	separador = separador ? separador : ',';
	var csv = [];
	var lines = texto.split('\n');
	if(headers === undefined) {
		headers = EppCsv._splitLine(lines.shift(), separador);
	}
   	for (var lineIdx = 0 ; lineIdx < lines.length; lineIdx++) {
   		var columns = EppCsv._splitLine(lines[lineIdx], separador);
   		if(columns === null) continue
   		var object = {};
   		headers.forEach(function(header, headerIdx){
   			object[header] = columns[headerIdx];
   		});
   		csv.push(object);
   	};
   	return csv;
}


EppCsv._splitLine = function (linha, separador, unescape) {
	if(linha === undefined || linha === null || linha.trim().length <= 0) return null
	var splitted = linha.split(separador);
	if(unescape === undefined || unescape) {
		for (var i = splitted.length - 1; i >= 0; i--) {
			splitted[i] = splitted[i].replace(/^["']/, '').replace(/["']$/, '')
		}
	}
	return splitted
}

/** 
 * Agrupa pelos valores na coluna keyCol.
 * groupFunc(rowa, rowb) recebe duas linhas e deve retornar a linha agrupada.
 */
EppCsv.group = function (tabular, keyCol, groupFunc) {
	var mapResultado = {};
	var keyOrder = [];

   	for (var linhaIdx = 0 ; linhaIdx < tabular.length; linhaIdx++) {
   		var linhaCorrente = tabular[linhaIdx];
   		var key = linhaCorrente[keyCol];
   		var linhaAgregada = mapResultado[key];
   		if(linhaAgregada) {
   			mapResultado[key] = groupFunc(linhaAgregada, linhaCorrente);
   		} else {
   			keyOrder.push(key);
   			mapResultado[key] = linhaCorrente;
   		}
   	};

   	var resultado = [];
   	keyOrder.forEach(function(key) {
   		resultado.push(mapResultado[key]);
   	});
   	return resultado;
}